package org.agent.aigccore.model.bo;

import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.agent.aigccore.basic.Global;
import org.agent.aigccore.basic.enums.TaskFlowRunRuleEnum;
import org.agent.aigccore.basic.enums.TaskFlowSplitTypeEnum;
import org.agent.aigccore.basic.enums.TaskFlowStatusEnum;
import org.agent.aigccore.basic.enums.TaskFlowTypeEnum;
import org.agent.aigccore.basic.serializable.BaseExtInfoBaseDBModel;
import org.agent.aigccore.basic.serializable.CustomConverter;
import org.agent.aigccore.model.dto.TaskFlowRunRuleMode;
import org.agent.aigccore.model.po.TaskFlowOrderPO;
import org.agent.aigccore.utils.StringUtil;
import org.mapstruct.DecoratedWith;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 任务流订单BO类
 */
@Slf4j
@Setter
@Getter
@Schema(description = "任务流订单业务对象")
public class TaskFlowOrderBO extends BaseExtInfoBaseDBModel {
    // ====== 基础信息
    /**
     * 业务ID
     */
    @Schema(description = "业务ID", example = "biz_123456")
    private String bizId;
    
    /**
     * 业务类型
     */
    @Schema(description = "业务类型", example = "CHAT")
    private TaskFlowTypeEnum bizType;
    
    /**
     * 名称
     */
    @Schema(description = "任务流名称", example = "聊天任务流")
    private String name;
    
    /**
     * 状态
     */
    @Schema(description = "任务流状态", example = "RUNNING")
    private TaskFlowStatusEnum status;
    
    /**
     * 用户ID
     */
    @Schema(description = "用户ID", example = "user123")
    private String userId;
    
    /**
     * 拆分类型
     */
    @Schema(description = "拆分类型", example = "SEQUENTIAL")
    private TaskFlowSplitTypeEnum splitType;
    
    /**
     * 链数据
     */
    @Schema(description = "链数据", example = "{}")
    private Map<String, Object> chainData;

    // ====== 运行模式
    /**
     * 运行规则
     */
    @Schema(description = "运行规则", example = "IMMEDIATE")
    private TaskFlowRunRuleEnum runRule;
    
    /**
     * 运行规则模式
     */
    @Schema(description = "运行规则模式")
    private TaskFlowRunRuleMode runRuleMode;

    // ====== 运行信息
    /**
     * 执行次数
     */
    @Schema(description = "执行次数", example = "5")
    private Integer execNum;
    
    /**
     * 失败次数
     */
    @Schema(description = "失败次数", example = "1")
    private Integer failNum;
    
    /**
     * 开始执行时间
     */
    @Schema(description = "开始执行时间", example = "2024-01-01T10:00:00")
    private Date startExecTime;
    
    /**
     * 截止执行时间
     */
    @Schema(description = "截止执行时间", example = "2024-01-01T18:00:00")
    private Date deadlineExecTime;
    
    /**
     * 首次执行时间
     */
    @Schema(description = "首次执行时间", example = "2024-01-01T10:00:00")
    private Date firstExecTime;
    
    /**
     * 最后执行时间
     */
    @Schema(description = "最后执行时间", example = "2024-01-01T15:00:00")
    private Date lastExecTime;

    // ====== 链信息
    /**
     * 根任务ID
     */
    @Schema(description = "根任务ID", example = "task_root_123")
    private String rootTaskId;
    
    /**
     * 终端任务ID
     */
    @Schema(description = "终端任务ID", example = "task_terminal_456")
    private String terminalTaskId;
    
    /**
     * 运行上游任务
     */
    @Schema(description = "运行上游任务列表", example = "[\"task1\", \"task2\"]")
    private List<String> runUpstreamTask;
    
    /**
     * 运行下游任务
     */
    @Schema(description = "运行下游任务列表", example = "[\"task3\", \"task4\"]")
    private List<String> runDownstreamTask;

    // ====== 外部业务信息
    /**
     * 链别名
     */
    @Schema(description = "链别名", example = "chat_chain")
    private String chainAlias;
    
    /**
     * 外部业务ID
     */
    @Schema(description = "外部业务ID", example = "ext_biz_789")
    private String outBizId;
    
    /**
     * 外部业务标识
     */
    @Schema(description = "外部业务标识", example = "CHAT_SESSION")
    private String outBizFlag;
    
    /**
     * 外部业务数据
     */
    @Schema(description = "外部业务数据", example = "{}")
    private Map<String, Object> outBizData;
    
    /**
     * 来源
     */
    @Schema(description = "来源", example = "aigccore")
    private String source = Global.APP_NAME;


    // ====== 其他
    /**
     * 环境
     */
    @Schema(description = "环境", example = "dev")
    private String env;
    
    /**
     * 日期
     */
    @Schema(description = "日期", example = "20240101")
    private String dt;
    
    /**
     * 执行系统
     */
    @Schema(description = "执行系统", example = "local")
    private String execSystem;
    
    /**
     * 自动触发
     */
    @Schema(description = "自动触发", example = "1")
    private Integer autoTrigger;


    // ============================== 转换器
    public static Convert convert = Mappers.getMapper(Convert.class);

    @Mapper(uses = CustomConverter.class)
    @DecoratedWith(AbstractDecoder.class)
    public interface Convert {
        @Mappings({@Mapping(target = "runRuleMode", ignore = true)
                , @Mapping(target = "runUpstreamTask", ignore = true)
                , @Mapping(target = "runDownstreamTask", ignore = true)
                , @Mapping(target = "chainData", ignore = true)
                , @Mapping(target = "outBizData", ignore = true)})
        TaskFlowOrderBO formPO(TaskFlowOrderPO po);

        @Mappings({@Mapping(target = "runRuleMode", ignore = true)
                , @Mapping(target = "runUpstreamTask", ignore = true)
                , @Mapping(target = "runDownstreamTask", ignore = true)
                , @Mapping(target = "chainData", ignore = true)
                , @Mapping(target = "outBizData", ignore = true)})
        TaskFlowOrderPO toPO(TaskFlowOrderBO bo);
    }

    public static abstract class AbstractDecoder implements Convert {
        private final Convert convert;

        public AbstractDecoder(Convert convert) {
            this.convert = convert;
        }

        @Override
        public TaskFlowOrderBO formPO(TaskFlowOrderPO po) {
            TaskFlowOrderBO bo = convert.formPO(po);
            if (Objects.nonNull(bo)) {
                bo.setName(StringUtil.isBlank(po.getName()) ? bo.getBizType().getDesc() : po.getName());
                bo.setChainData(JSON.parseObject(po.getChainData(), Map.class));
                bo.setOutBizData(JSON.parseObject(po.getOutBizData(), Map.class));
                bo.setRunUpstreamTask(StringUtil.convertListByComma(po.getRunUpstreamTask()));
                bo.setRunDownstreamTask(StringUtil.convertListByComma(po.getRunDownstreamTask()));
                bo.setRunRuleMode(JSON.parseObject(po.getRunRuleMode(), TaskFlowRunRuleMode.class));
            }
            return bo;
        }

        @Override
        public TaskFlowOrderPO toPO(TaskFlowOrderBO bo) {
            TaskFlowOrderPO po = convert.toPO(bo);
            if (Objects.nonNull(po)) {
                po.setChainData(JSON.toJSONString(bo.getChainData()));
                po.setOutBizData(JSON.toJSONString(bo.getOutBizData()));
                po.setRunUpstreamTask(StringUtil.convertStrByComma(bo.getRunUpstreamTask()));
                po.setRunDownstreamTask(StringUtil.convertStrByComma(bo.getRunDownstreamTask()));
                po.setRunRuleMode(JSON.toJSONString(bo.getRunRuleMode()));
            }
            return po;
        }
    }
}
